#include "decoder.h"

#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavutil/channel_layout.h>

#include "events.h"
#include "trait/frame_sink.h"
#include "util/log.h"

/** 
 * Downcast packet_sink to decoder 
 * 通过packet_sink包找到 sc_decoder的地址
 * @param SINK 
 * */
#define DOWNCAST(SINK) container_of(SINK, struct sc_decoder, packet_sink)

/*

@param decoder 自定义解码器上下文
@param codec AVCodec是存储编解码器信息的结构体, 每种视频（音频）编解码器对应一个该结构体
@return 成功返回true,失败返回false
*/
static bool
sc_decoder_open(struct sc_decoder *decoder, AVCodecContext *ctx) {
    decoder->frame = av_frame_alloc();
    if (!decoder->frame) {
        LOG_OOM();
        return false;
    }

    if (!sc_frame_source_sinks_open(&decoder->frame_source, ctx)) {
        av_frame_free(&decoder->frame);
        return false;
    }

    decoder->ctx = ctx;

    return true;
}

static void
sc_decoder_close(struct sc_decoder *decoder) {
    sc_frame_source_sinks_close(&decoder->frame_source);

    /*
    av_frame_alloc申请内存
    av_frame_unref，释放音视频数据资源
    av_frame_free是释放所有资源，包括音视频数据资源和结构体本身的内存。
    可以从源码中看到，av_frame_free函数体内是先调用了av_frame_unref释放数据缓存，再free本身结构体内存。
    */    
    av_frame_free(&decoder->frame);
}

/*

@param decoder 自定义解码器
@param packet 编码的音视频帧数据
@return 成功解出帧数据返回true，否则返回false
*/
static bool
sc_decoder_push(struct sc_decoder *decoder, const AVPacket *packet) {
        // https://zhuanlan.zhihu.com/p/575277254
    bool is_config = packet->pts == AV_NOPTS_VALUE;
    if (is_config) {
        // nothing to do
        return true;
    }

    /*
    https://blog.csdn.net/fuhanghang/article/details/123792724
    音视频解码步骤分为两步，
    第一步avcodec_send_packet，
    第二步avcodec_receive_frame，
    
    通过接口名字我们就可以知道第一步是发送编码数据包，第二步是接收解码后数据

    avcodec_send_packet和avcodec_receive_frame调用关系并不一定是一对一的，
    比如一些音频数据一个AVPacket中包含了1秒钟的音频，调用一次avcodec_send_packet之后，
    可能需要调用25次 avcodec_receive_frame才能获取全部的解码音频数据
    */
    int ret = avcodec_send_packet(decoder->ctx, packet);
    if (ret < 0 && ret != AVERROR(EAGAIN)) {
        LOGE("Decoder '%s': could not send video packet: %d",
             decoder->name, ret);
        return false;
    }

    for (;;) {
        ret = avcodec_receive_frame(decoder->ctx, decoder->frame);
        if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
            break;
        }

        if (ret) {
        /*
        AVERROR(EAGAIN)是一个常见的错误码，它实际上并不是真的报错
        而是代表解码数据不足，需要提供更多的AVPacket才能解码出数据
        解决方法：
        继续调用avcodec_send_packet发送数据，直到解码数据足够为止
        */            
            LOGE("Decoder '%s', could not receive video frame: %d",
                 decoder->name, ret);
            return false;
        }

        // a frame was received
        bool ok = sc_frame_source_sinks_push(&decoder->frame_source,
                                             decoder->frame);
        av_frame_unref(decoder->frame);
        if (!ok) {
            // Error already logged
            return false;
        }
    }

    return true;
}

/*

@param sink 必须是是 sc_decoder->packet_sink
@param codec
@return 
*/
static bool
sc_decoder_packet_sink_open(struct sc_packet_sink *sink, AVCodecContext *ctx) {
    // AVCodec是存储编解码器信息的结构体, 每种视频（音频）编解码器对应一个该结构体.这是原来的参数
    struct sc_decoder *decoder = DOWNCAST(sink);
    return sc_decoder_open(decoder, ctx);
}

static void
sc_decoder_packet_sink_close(struct sc_packet_sink *sink) {
    struct sc_decoder *decoder = DOWNCAST(sink);
    sc_decoder_close(decoder);
}

static bool
sc_decoder_packet_sink_push(struct sc_packet_sink *sink,
                            const AVPacket *packet) {
    struct sc_decoder *decoder = DOWNCAST(sink);
    return sc_decoder_push(decoder, packet);
}

void
sc_decoder_init(struct sc_decoder *decoder, const char *name) {
    decoder->name = name; // statically allocated
    sc_frame_source_init(&decoder->frame_source);

    static const struct sc_packet_sink_ops ops = {
        .open = sc_decoder_packet_sink_open,
        .close = sc_decoder_packet_sink_close,
        .push = sc_decoder_packet_sink_push,
    };

    decoder->packet_sink.ops = &ops;
}
